package cn.wolfcode.service.impl;

import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.common.web.Result;
import cn.wolfcode.domain.Product;
import cn.wolfcode.domain.SeckillProduct;
import cn.wolfcode.domain.SeckillProductVo;
import cn.wolfcode.mapper.SeckillProductMapper;
import cn.wolfcode.redis.SeckillRedisKey;
import cn.wolfcode.service.ISeckillProductService;
import cn.wolfcode.web.feign.ProductFeignApi;
import cn.wolfcode.web.msg.SeckillCodeMsg;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;


@Service
@Slf4j
public class SeckillProductServiceImpl implements ISeckillProductService {
    @Autowired
    private SeckillProductMapper seckillProductMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private ProductFeignApi productFeignApi;

    @Override
    public List<SeckillProductVo> queryCurrentListByTime(Integer time) {
        //查询秒杀商品的数据
        List<SeckillProduct> seckillProducts = seckillProductMapper.queryCurrentlySeckillProduct(time);
        //如果查询结果为空，返回空集合
        if (seckillProducts == null || StringUtils.isEmpty(seckillProducts)) {
            return Collections.emptyList();
        }
        List<Long> ids = new ArrayList<>();
        //遍历秒杀商品集合，将秒杀商品的 productId 放到List<Long>集合中
        for (SeckillProduct seckillProduct : seckillProducts) {
            ids.add(seckillProduct.getProductId());
        }
        //远程调用商品服务，使用ids集合查询秒杀商品的基本信息
        Result<List<Product>> productResult = productFeignApi.queryProductByIds(ids);
        //如果查询结果为空，抛出商品异常， 返回{code:500208,msg:"商品服务繁忙,请稍后再试"},
        if (productResult == null || productResult.hasError()) {
            throw new BusinessException(SeckillCodeMsg.PRODUCT_SERVER_ERROR);
        }
        //拿到所有商品的集合
        List<Product> productList = productResult.getData();
        //遍历商品集合，将商品id作为key,商品作为value，放到map集合中
        Map<Long, Product> productMap = new HashMap<>();
        for (Product product : productList) {
            productMap.put(product.getId(), product);
        }
        SeckillProductVo seckillProductVo;
        List<SeckillProductVo> seckillProductVos = new ArrayList<>();
        //进行聚合操作
        //遍历秒杀商品
        for (SeckillProduct seckillProduct : seckillProducts) {
            //使用秒杀商品的 商品id作为key，查询商品的map集合，得到商品信息
            Product product = productMap.get(seckillProduct.getProductId());
            seckillProductVo = new SeckillProductVo();
            //顺序不能变，BeanUtils.copyProperties(seckillProduct, seckillProductVo)必须在后面复制，需要放后面，需要的是秒杀商品id
            BeanUtils.copyProperties(product, seckillProductVo);
            BeanUtils.copyProperties(seckillProduct, seckillProductVo);
            seckillProductVos.add(seckillProductVo);
        }
        return seckillProductVos;
    }

    @Override
    public List<SeckillProductVo> queryByTime(String time) {
        Map<Object, Object> seckillProductMap = redisTemplate.opsForHash()
                .entries(SeckillRedisKey.SECKILL_PRODUCT_LIST.getRealKey(time));
        List<SeckillProductVo> seckillProductVos = new ArrayList<>();
        for (Map.Entry<Object, Object> seckillProductEntry : seckillProductMap.entrySet()) {
            seckillProductVos.add(JSON.parseObject((String) seckillProductEntry.getValue(), SeckillProductVo.class));
        }
        return seckillProductVos;
    }

    @Override
    public SeckillProductVo find(int time, Long seckillId) {
        Object objJson = redisTemplate.opsForHash().get(SeckillRedisKey.SECKILL_PRODUCT_LIST.getRealKey(String.valueOf(time)), String.valueOf(seckillId));
        if (StringUtils.isEmpty(objJson)) {
            return null;
        }
        return JSON.parseObject(String.valueOf(objJson), SeckillProductVo.class);
    }

    @Override
    public int decrStock(Long seckillId) {
        return seckillProductMapper.decrStock(seckillId);
    }

    @Override
    public void syncRedisStockCount(Long seckillId, Integer time) {
        //把真实库存查询出来
        int stockCount = seckillProductMapper.getStockCount(seckillId);
        //把真实库存重新存放Redis当中
        redisTemplate.opsForHash().put(SeckillRedisKey.SECKILL_STOCK_COUNT_HASH
                        .getRealKey(String.valueOf(time))
                , String.valueOf(seckillId)
                , String.valueOf(stockCount));
        log.info("数据同步成功");
    }
}
